﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.Xml.Serialization;

namespace zEngine.Cameras
{
    public class KeyboardControlCamera : Camera
    {
        private TimeSpan _lastAction = TimeSpan.MinValue;
        private TimeSpan _delayPeriod = TimeSpan.FromMilliseconds(100.0f); // Delay between actions. Prevent multiple action in one click
        private float _moveSize = 10.0f;

        /// <summary>
        /// Initializes a new instance of the KeyboardControlCamera class.
        /// </summary>
        public KeyboardControlCamera(Game game, Vector3 cameraPosition, Vector3 cameraTarget):base(game,cameraPosition, cameraTarget)
        {
        }

        public override void Update(GameTime gameTime)
        {
            if (gameTime.TotalGameTime > _lastAction.Add(_delayPeriod))
            {
                ProcessInputKey();
                _lastAction = gameTime.TotalGameTime;
            }
            base.Update(gameTime);
        }

        public void ProcessInputKey()
        {
            KeyboardState ks = Keyboard.GetState();
            GamePadState gps = GamePad.GetState(PlayerIndex.One, GamePadDeadZone.IndependentAxes);
            Vector2 lts = gps.ThumbSticks.Left;
            Vector2 rts = gps.ThumbSticks.Right;

            #region GamePadControl
            if (lts.Y != 0)
            {
                CameraTarget += Direction * (MoveSize * lts.Y);
                CameraPosition += Direction * (MoveSize * lts.Y);
            }
            if (lts.X != 0)
            {
                // Find the vector perpendicular with direction vector
                Vector3 sideDirection = Vector3.Cross(Direction, CameraUp);
                sideDirection.Normalize();
                // Move
                CameraPosition += sideDirection * (MoveSize * lts.X);
                CameraTarget += sideDirection * (MoveSize * lts.X);
            }
            if (rts.Y != 0)
            {
                CameraPosition.Y += MoveSize * rts.Y;
                if (gps.IsButtonDown(Buttons.LeftTrigger))
                {
                    CameraTarget.Y += MoveSize *rts.Y;
                }
            }
            if (rts.X != 0)
            {
                CameraPosition = Vector3.Transform(CameraPosition, Matrix.CreateRotationY(MathHelper.ToRadians(MoveSize * rts.X)));
            }
            #endregion

            #region KeyboardControl
            // Move keys
            if (ks.IsKeyDown(Keys.W))
            {
                CameraPosition += Direction * MoveSize;
                CameraTarget += Direction * MoveSize;
            }
            if (ks.IsKeyDown(Keys.S))
            {
                CameraPosition -= Direction * MoveSize;
                CameraTarget -= Direction * MoveSize;
            }
            if (ks.IsKeyDown(Keys.A))
            {
                // Find the vector perpendicular with direction vector
                Vector3 sideDirection = Vector3.Cross(Direction, CameraUp);
                sideDirection.Normalize();
                // Move
                CameraPosition -= sideDirection * MoveSize;
                CameraTarget -= sideDirection * MoveSize;
            }
            if (ks.IsKeyDown(Keys.D))
            {
                // Find the vector perpendicular with direction vector
                Vector3 sideDirection = Vector3.Cross(Direction, CameraUp);
                sideDirection.Normalize();
                // Move
                CameraPosition += sideDirection * MoveSize;
                CameraTarget += sideDirection * MoveSize;
            }

            // Tilt or move camera up down
            if (ks.IsKeyDown(Keys.Up))
            {
                CameraPosition.Y += MoveSize;
                if (ks.IsKeyDown(Keys.LeftShift))
                {
                    CameraTarget.Y += MoveSize;
                }
            }
            if (ks.IsKeyDown(Keys.Down))
            {
                CameraPosition.Y -= MoveSize;
                if (ks.IsKeyDown(Keys.LeftShift))
                {
                    CameraTarget.Y -= MoveSize;
                }
            }

            // Rotate
            if (ks.IsKeyDown(Keys.Left))
            {
                CameraPosition = Vector3.Transform(CameraPosition, Matrix.CreateRotationY(MathHelper.ToRadians(MoveSize)));
            }
            if (ks.IsKeyDown(Keys.Right))
            {
                CameraPosition = Vector3.Transform(CameraPosition, Matrix.CreateRotationY(MathHelper.ToRadians(-MoveSize)));
            }
            #endregion

        }

        #region Properties
        public float MoveSize
        {
            get { return _moveSize; }
            set { _moveSize = value; }
        }        
        [XmlIgnore]
        public TimeSpan LastAction
        {
            get { return _lastAction; }
            set { _lastAction = value; }
        }
        public TimeSpan DelayPeriod
        {
            get { return _delayPeriod; }
            set { _delayPeriod = value; }
        }
        #endregion

    }
}
